//
//  YXCuteView.swift
//  UIBezierPath实现果冻效果
//
//  Created by Rookie_YX on 16/7/6.
//  Copyright © 2016年 YX_Rookie. All rights reserved.
//

import UIKit

let screenWidth:CGFloat = UIScreen.mainScreen().bounds.size.width
let screenHeight:CGFloat = UIScreen.mainScreen().bounds.size.height
let min_height:CGFloat = 100

// 监听r5点x,y坐标
let kX: String = "curveX"
let kY: String = "curveY"

class YXCuteView: UIView {
  
  var mHeight:CGFloat = 0
  var curveX:CGFloat = 0      // r5点x坐标
  var curveY:CGFloat = 0      // r5点y坐标
  var curveView:UIView = UIView()  // r5红点
  var shapeLayer:CAShapeLayer = CAShapeLayer()
  var displayLink:CADisplayLink = CADisplayLink()
  var isAnimating:Bool = false
  
  override init(frame: CGRect) {
    super.init(frame: frame)
    self.backgroundColor = UIColor.whiteColor()
    // 监听
    self.addObserver(self, forKeyPath: kX, options: NSKeyValueObservingOptions.New, context: nil)
    self.addObserver(self, forKeyPath: kY, options: NSKeyValueObservingOptions.New, context: nil)
    // UI
    configuration()
    configCurveView()
    configShapeLayer()
    
    observerObject()
  }
  
  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
  
  override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>){
    print("enter observer")
    if keyPath == kX || keyPath == kY {
      updateShapeLayerPath()
    }
  }
  // 移除监听
  deinit{
    self.removeObserver(self, forKeyPath: kX)
    self.removeObserver(self, forKeyPath: kY)
  }
  
  // MARK:- 监听
  func observerObject(){
    self.willChangeValueForKey(kX)
    self.willChangeValueForKey(kY)
    self.didChangeValueForKey(kX)
    self.didChangeValueForKey(kY)
  }
}

extension YXCuteView{
  
  // MARK:- Configuration
  private func configuration(){
    
    mHeight = 100        // 手势一定相对高度
    isAnimating = false  // 是否处于动效状态
    
    // 手势
    let pan = UIPanGestureRecognizer(target: self, action: #selector(YXCuteView.handlePanAction(_:)))
    self.addGestureRecognizer(pan)
    
    // CADisplayLink默认每秒运行60次calculatePath是算出在运行期间_curveView的坐标，从而确定_shapeLayer的形状
    displayLink = CADisplayLink(target: self, selector: #selector(YXCuteView.calculatePath))
    displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
    displayLink.paused = true
    
  }
  
  private func configShapeLayer(){
    
    shapeLayer = CAShapeLayer()
    shapeLayer.frame = CGRect(x: 0, y: 0, width: screenWidth, height: 200)
    shapeLayer.fillColor = UIColor.orangeColor().CGColor
    self.layer.addSublayer(shapeLayer)
  }
  
  private func configCurveView(){
    
    // CurveView就是r5点
    self.curveX = screenWidth / 2.0     // r5点x坐标
    self.curveY = min_height            // r5点y坐标
    curveView = UIView(frame: CGRect(x: self.curveX, y: self.curveY, width: 3, height: 3))
    curveView.backgroundColor = UIColor.orangeColor()
    self.addSubview(curveView)
  }
  
  // MARK:- 手势事件
  func handlePanAction(pan:UIPanGestureRecognizer){
    
    if !isAnimating {
      if pan.state == UIGestureRecognizerState.Changed {
        
        // 手势移动时, shapeLayer跟着手势乡下扩大区域
        let point:CGPoint = pan.translationInView(self)
        
        // 这部分代码使r5红点跟着手势走
        mHeight = point.y * 0.7 + min_height
        self.curveX = screenWidth / 2.0 + point.x
        self.curveY = mHeight > min_height ? mHeight : min_height
        curveView.frame = CGRect(x: curveX, y: curveY, width: curveView.frame.size.width, height: curveView.frame.size.height)
        print("curveView.frame \(curveView.frame)")
        observerObject()
      }
      else if pan.state == UIGestureRecognizerState.Cancelled ||
        pan.state == UIGestureRecognizerState.Ended ||
        pan.state == UIGestureRecognizerState.Failed{
        // 手势结束时,shapeLayer返回原状并产生弹簧动效
        isAnimating = true
        displayLink.paused = false //开启displaylink,会执行方法calculatePath.
        observerObject()
        // 弹簧动效
        UIView.animateWithDuration(0.1, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.1, options: .CurveEaseInOut, animations: {
          
          // 曲线点(r5点)是一个view.所以在block中有弹簧效果.然后根据他的动效路径,在calculatePath中计算弹性图形的形状
          self.curveView.frame = CGRect(x: screenWidth / 2.0, y: min_height, width: 3, height: 3)
          self.observerObject()
          }, completion: { (finishded:Bool) in
            
            if finishded{
              self.displayLink.paused = true
              self.isAnimating = false
              // path恢复
              self.updateShapeLayerPath()
            }
        })
      }
    }
  }
  
  // MARK:- 链接对象方法
  func calculatePath(){
    
    // 由于手势结束时,r5执行了一个UIView的弹簧动画,把这个过程的坐标记录下来,并相应的画出_shapeLayer形状
    let layer:CALayer = curveView.layer.presentationLayer() as! CALayer
    self.curveX = layer.position.x
    self.curveY = layer.position.y
  }
  
  private func updateShapeLayerPath(){
    print(#function)
    // 更新_shapeLayer形状
    let tpath:UIBezierPath = UIBezierPath()
    tpath.moveToPoint(CGPoint(x: 0, y: 0))   // r1点
    tpath.addLineToPoint(CGPoint(x: screenWidth, y: 0)) // r2点
    tpath.addLineToPoint(CGPoint(x: screenWidth, y: min_height)) // r4点
    tpath.addQuadCurveToPoint(CGPoint(x: 0, y: min_height), controlPoint: CGPoint(x: curveX, y: curveY)) // r3,r4,r5确定的一个弧线
    tpath.closePath()
    shapeLayer.path = tpath.CGPath
  }
}
